#include "UserWidget/WidgetComponent/PlayerLevelWidget.h"
#include "Components/TextBlock.h"
#include "Components/ProgressBar.h"
#include "Kismet/KismetMathLibrary.h"
#include "Libraries/GameKitFL.h"
#include "Libraries/CommonLibrary.h"

void UPlayerLevelWidget::NativeOnInitialized() {
	Super::NativeOnInitialized();
	XPFromMission = 0.f;
	CurrentXP = 0.f;
	Percentage = 0.f;
	TargetXP = 0.f;
	CharacterLevel = 1;
	NeededXP = 100.f;
	NeededXPMultiplier = 2.f;
	TotalXP = 0.f;
	LevelProgress->PercentDelegate.BindUFunction(this, "UpdateProgressBar");
}

void UPlayerLevelWidget::NativeConstruct() {
	Super::NativeConstruct();
	LoadVariables();
	UpdatePlayerLevel(CharacterLevel);
}

void UPlayerLevelWidget::ConstructWidget(FSavedPlayerLevel LPlayerLevel){
	PlayerLevel = LPlayerLevel;
}
void UPlayerLevelWidget::ReceiveXP(float LXPValue){
	XPFromMission = LXPValue;
	TargetXP = CurrentXP + XPFromMission;
	TotalXP += XPFromMission;
	ToggleProgressBar(true);
	FTimerHandle UniquHandle;
	FTimerDelegate RespawnDelegate = FTimerDelegate::CreateLambda([this]() {
		FTimerDelegate respawnDelegate = FTimerDelegate::CreateUObject(this, &UPlayerLevelWidget::UpdateXP);
		GetWorld()->GetTimerManager().SetTimer(this->UpdateXPTimerHandle, respawnDelegate, 0.01, true);
	});
	GetWorld()->GetTimerManager().SetTimer(UniquHandle, RespawnDelegate, 0.25, false);
}

void UPlayerLevelWidget::ToggleProgressBar(bool Visible){
	if (Visible) {
		if (IsVisible) return;
		UWidgetAnimation* Temp = UCommonLibrary::GetAnimInstance(GetClass(), FText::FromString("Progress"));
		PlayAnimation(Temp, 0.f, 1, Visible ? EUMGSequencePlayMode::Forward : EUMGSequencePlayMode::Reverse);
		IsVisible = Visible;
	}
	else {
		if (!IsVisible) return;
		if (GetWorld()->GetTimerManager().IsTimerActive(RetriggerableHandle)) {
			GetWorld()->GetTimerManager().ClearTimer(RetriggerableHandle);
		}
		FTimerDelegate RespawnDelegate = FTimerDelegate::CreateLambda([this, Visible]() {
			UWidgetAnimation* Temp = UCommonLibrary::GetAnimInstance(GetClass(), FText::FromString("Progress"));
			PlayAnimation(Temp, 0.f, 1, Visible ? EUMGSequencePlayMode::Forward : EUMGSequencePlayMode::Reverse);
			this->IsVisible = Visible;
			// DEBUG_MESSAGE("%i", IsVisible ? 1 : 0);
		});
		GetWorld()->GetTimerManager().SetTimer(RetriggerableHandle, RespawnDelegate, 2.f, false);
	}
}

void UPlayerLevelWidget::UpdateXP(){
	CurrentXP = UKismetMathLibrary::FInterpTo_Constant(CurrentXP, TargetXP, GetWorld()->GetDeltaSeconds(), 50.f);
	Percentage = FMath::Clamp(UKismetMathLibrary::NormalizeToRange(CurrentXP, 0.f, NeededXP), 0.f, 1.f);
	if (Percentage == 1.f) {
		TargetXP -= NeededXP;
		CurrentXP = 0.f;
		NeededXP *= NeededXPMultiplier;
		CharacterLevel += 1;
		UpdatePlayerLevel(CharacterLevel);
		SaveVariables();
	}
	else {
		if (CurrentXP == TargetXP) {
			ToggleProgressBar(false);
			GetWorld()->GetTimerManager().ClearTimer(UpdateXPTimerHandle);
			SaveVariables();
		}
	}
}

void UPlayerLevelWidget::UpdatePlayerLevel(int32 Value){
	LevelText->SetText(FText::AsNumber(Value));
}

float UPlayerLevelWidget::UpdateProgressBar(){
	return Percentage;
}

void UPlayerLevelWidget::LoadVariables(){
	CharacterLevel = PlayerLevel.PlayerLevel;
	CurrentXP = PlayerLevel.CurrentXP;
	TotalXP = PlayerLevel.TotalXP;
	NeededXP= PlayerLevel.NeededXP;
	NeededXPMultiplier = PlayerLevel.NeededXPMultiplier;
	Percentage = FMath::Clamp(UKismetMathLibrary::NormalizeToRange(CurrentXP, 0.f, NeededXP), 0.f, 1.f);
}

void UPlayerLevelWidget::SaveVariables(){
	FSavedPlayerInfo Temp = UGameKitFL::GetPlayerSaveData();
	Temp.PlayerLevel.PlayerLevel = CharacterLevel;
	Temp.PlayerLevel.CurrentXP = CurrentXP;
	Temp.PlayerLevel.TotalXP = TotalXP;
	Temp.PlayerLevel.NeededXP = NeededXP;
	Temp.PlayerLevel.NeededXPMultiplier = NeededXPMultiplier;
	UGameKitFL::UpdatePlayerSaveData(Temp);
}